通过本案例,你将学会:
物流行业的数据分析通常围绕四个关键维度展开:
| 维度 | 核心指标 | 分析目标 |
|---|---|---|
| 时效性 | 按时交货率 | 配送服务是否达标 |
| 质量 | 合格率、返修率 | 产品是否存在缺陷 |
| 区域 | 各区域表现对比 | 识别薄弱区域 |
| 货品 | 各货品销售与反馈 | 识别问题货品 |
本案例的数据清洗包含以下关键步骤:
drop_duplicates() 保留首次出现的记录dropna() 删除含缺失值的行drop(columns=['订单行']) 移除无用字段reset_index(drop=True) 更新行索引# 注:data_wuliu.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import os # 导入操作系统接口模块
import pandas as pd # 导入Pandas数据分析库
import numpy as np # 导入NumPy数值计算库
import matplotlib.pyplot as plt # 导入Matplotlib绑图库
plt.rcParams['font.sans-serif'] = 'SimHei' ## 设置中文显示
## 数据清洗部分
data = pd.read_csv('data_wuliu.csv',encoding='gbk')
#删除重复记录
data.drop_duplicates(keep='first',inplace=True) #keep='first'默认值,保留第一次出现的重复记录
#删除缺失值
data.dropna(axis=0,how='any',inplace=True)
#删除订单行
data.drop(columns=['订单行'],inplace=True,axis=1)
print(data.info()) # 输出数据框基本信息
#更新索引(drop=True:把原来的索引index列删除,重置index)
data.reset_index(drop=True,inplace=True)
def data_deal(number): # 定义函数data_deal
if number.find('万元')!= -1:#找到带有万元的,取出数字,去掉逗号,转成float,*10000
number_new = float(number[:number.find('万元')].replace(',',''))*10000 # 替换数据中的指定值
pass # 占位符,暂不执行任何操作
else: #找到带有元的,删除元,删除逗号,转成float
number_new = float(number.replace('元','').replace(',','')) # 替换数据中的指定值
pass # 占位符,暂不执行任何操作
return number_new # 返回计算结果
data['销售金额'] = data['销售金额'].map(data_deal) # 对数据进行映射转换
print(data.describe()) # 输出描述性统计信息
#销售金额为0的情况,删除
data = data[data['销售金额']!=0].copy()
data['销售时间'] = pd.to_datetime(data['销售时间']) # 转换为日期时间格式
data['交货时间'] = pd.to_datetime(data['交货时间']) # 转换为日期时间格式
data['销售月份'] = data['销售时间'].dt.month # 提取日期时间属性
data['交货月份'] = data['交货时间'].dt.month # 提取日期时间属性
#1.配送是否存在问题研究
#月份维度
data['货品交货状况'] = data['货品交货状况'].str.strip()
data1 = data.groupby(['销售月份','货品交货状况']).size().unstack() #unstack()把行索引变成列索引
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货']) # 提取按时交货列作为data1['按时交货率']变量
print("月份交货状况:\n",data1) # 输出月份交货状况:\n
data1 = data.groupby(['销售区域','货品交货状况']).size().unstack() # 按指定列分组聚合
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货']) # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False) # 按指定列排序
print("销售区域交货状况:\n",data1) # 输出销售区域交货状况:\n
#泰国地区的按时交货率最高,西北地区的按时交货率最低,而且非常明显,可以看出,西北地区的配送服务存在问题,需要重点关注
#货品维度
data1 = data.groupby(['货品','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货']) # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False) # 按指定列排序
print("不同货品交货状况:\n",data1) # 输出不同货品交货状况:\n
#可以看出货品4的按时交货率最低
#货品和销售区域结合
data1 = data.groupby(['货品','销售区域','货品交货状况']).size().unstack()
data1['按时交货率'] = data1['按时交货']/(data1['按时交货']+data1['晚交货']) # 提取按时交货列作为data1['按时交货率']变量
data1 = data1.sort_values(data1.columns[-1],ascending=False) # 按指定列排序
print("货品和销售区域结合的交货状况:\n",data1) # 输出货品和销售区域结合的交货状况:\n
#2.是否存在尚有潜力的销售区域问题研究
#月份维度
data_month = data.groupby(['销售月份','货品'])['数量'].sum().unstack()
print("月份维度货品的销售情况:\n",data_month) # 输出月份维度货品的销售情况:\n
# 绘制各个月份的销售情况
data_month.plot(kind='line',figsize=(12,6))
plt.title('各个月份的销售情况') # 设置图表标题
plt.savefig("1.png") # 保存图形至文件
#货品2在10月和12月销量猛增,有可能是公司加大了营销力度,也有可能是开发了新的市场
#销售区域维度
data_region = data.groupby(['销售区域','货品'])['数量'].sum().unstack()
print("销售区域货品的销售情况:\n",data_region) # 输出销售区域货品的销售情况:\n
#从销售区域看,每种货品销售区域为1-3个,货品1有三个销售区域,货品2有两个销售区域,货品3、4、5、6只有一个销售区域,货品2在华东地区还有较大市场空间,适合加大投入,同时货品2在西北配送时效长,用户拒收率高,从成本角度考虑,应该减少投入。
#月份和区域结合
data_month_region = data.groupby(['销售月份','销售区域','货品'])['数量'].sum().unstack()
data_month_region['货品2'] # 查看货品2在各月份和区域的销售数量
#货品2没有开发新的市场,而是在华东地区加大了营销力度 可以在7,8,9月份加大华东地区的营销力度
#3.商品是否存在质量问题研究
data['货品用户反馈'] = data['货品用户反馈'].str.strip()
data3 = data.groupby(['货品','销售区域'])['货品用户反馈'].value_counts().unstack() # 按指定列分组聚合
data3['拒货率'] = data3['拒货']/data3.sum(axis=1) # 计算总和
data3['合格率'] = data3['质量合格']/data3.sum(axis=1) # 计算总和
data3['返修率'] = data3['返修']/data3.sum(axis=1) # 计算总和
# 按合格率、返修率、拒货率降序排列以识别质量问题货品
data3.sort_values(['合格率','返修率','拒货率'],ascending=False)
#货品3 6 5 的合格率较高,返修率较低,货品1 2 4 的合格率较低,返修率较高,货品1、2、4质量存在问题,建议扩大抽检范围,增大质检力度 货品2在马来西亚的拒货率最高,按时交货率最低,猜测马来西亚对时效性要求较高,需要提高时效性。货品2在马来西亚的销售量较低,可以考虑减少投入。原始数据中销售金额的格式不统一,需要转换为数值类型:
| 原始格式 | 转换逻辑 | 转换结果 |
|---|---|---|
'5万元' |
提取数字 × 10000 | 50000.0 |
'12,345元' |
删除逗号和’元’ | 12345.0 |
'1,234.5万元' |
删除逗号 × 10000 | 12345000.0 |
def data_deal(number):
"""处理销售金额,统一转换为元(float类型)"""
if number.find('万元') != -1:
# 包含'万元':提取数字部分,去逗号,乘以10000
number_new = float(
number[:number.find('万元')].replace(',', '')
) * 10000
else:
# 包含'元':直接去掉'元'和逗号
number_new = float(
number.replace('元', '').replace(',', '')
)
return number_new
# 使用 map() 将转换函数应用到整列
data['销售金额'] = data['销售金额'].map(data_deal)将字符串类型的日期转换为 datetime,并提取月份特征:
pd.to_datetime() 将字符串解析为日期对象.dt.month 提取月份数值.copy() 创建副本,避免 SettingWithCopyWarning配送时效性是物流服务的核心 KPI,分析从三个维度切入:
按月统计按时交货 vs 晚交货的订单数,计算按时交货率:
groupby().size() 统计每个分组的记录数unstack() 将行索引转为列索引,形成交叉表按销售区域计算按时交货率,并降序排列以快速识别问题区域:
关键发现:泰国地区按时交货率最高,西北地区最低,配送服务需重点关注。
进一步细分到货品层面,识别哪些货品的配送问题最严重:
关键发现:货品4的按时交货率最低,需要优先改进其物流方案。
将货品和区域两个维度结合,精确定位问题组合:
交叉分析能精确定位「哪个货品在哪个区域」出了问题。
从月份维度分析各货品的销售数量变化趋势:
['数量'].sum() 对销售数量求和unstack() 将货品从行索引转为列使用折线图展示各货品销售数量随月份的变化:
关键发现:货品2在10月和12月销量猛增,可能源于营销力度加大。
分析各货品在不同销售区域的覆盖情况:
关键发现:
结合月份和区域,判断货品2销量增长的来源:
结论:货品2并未开发新市场,而是在华东地区加大了营销力度。建议在 7~9 月份继续加大华东地区的投入。
基于用户反馈数据,计算三个质量指标:
| 指标 | 计算公式 | 期望方向 |
|---|---|---|
| 合格率 | 质量合格数 / 总数 | 越高越好 |
| 返修率 | 返修数 / 总数 | 越低越好 |
| 拒货率 | 拒货数 / 总数 | 越低越好 |
# 清洗用户反馈字段
data['货品用户反馈'] = data['货品用户反馈'].str.strip()
# 按货品和区域分组,统计各类反馈数量
data3 = data.groupby(
['货品', '销售区域']
)['货品用户反馈'].value_counts().unstack()
# 计算三大质量指标
data3['拒货率'] = data3['拒货'] / data3.sum(axis=1)
data3['合格率'] = data3['质量合格'] / data3.sum(axis=1)
data3['返修率'] = data3['返修'] / data3.sum(axis=1)
# 按合格率降序排列
data3 = data3.sort_values(
['合格率', '返修率', '拒货率'], ascending=False
)
print(data3)问题发现:
改进建议:
问题发现:
改进建议:
问题发现:
改进建议:
| 技术要点 | 对应方法 |
|---|---|
| 数据清洗 | drop_duplicates(), dropna(), str.strip() |
| 数据转换 | 自定义函数 + map() |
| 日期处理 | pd.to_datetime(), .dt.month |
| 分组聚合 | groupby().size(), groupby().sum() |
| 交叉分析 | unstack(), value_counts() |
| 多列排序 | sort_values() |
| 可视化 | DataFrame.plot(kind='line') |
[商业大数据分析与应用]